#pragma once
/** \file fishmytest.h
  * \brief Example implentation of the IFishLibrary interface.
  * \defgroup fishmytest Example implementation of the IFishLibrary interface
  * \addtogroup fishmytest
  * @{
  */
#include "fish/interface/ifishlibrary.h"
using namespace itasca;

/** \brief Example implementation of the IFishLibrary interface.
  *
  * Defines a class that when loaded as an Itasca DLL plugin creates seven new FISH intrinsics.\n
  * These intrinsics allow the user to create the data for a sinusoidal Table, at a specified
  *   frequency, amplitude, phase, sampling interval, and length.
  * The functions created are:
  *    - mytest_freq      The frequency to use
  *    - mytest_amp       The amplitude
  *    - mytest_phase     The phase
  *    - mytest_int       The interval
  *    - mytest_num       The number of points, interval*num is the length (or duration).
  *    - mytest_all       Allows specifying all of the above at once.
  *    - mytest_create    Creates the table data using the above parameters.
  */
class FishMytest
	: public IFishLibrary
{
public:
	/// This enum is used to define ID numbers for the seven different FISH functions.
	enum Functions
	{
		FreqFunction = 0,
		///< mytest_freq ID number
		AmpFunction,
		///< mytest_amp ID number
		PhaseFunction,
		///< mytest_phase ID number
		IntervalFunction,
		///< mytest_int ID number
		NumberFunction,
		///< mytest_num ID number
		AllFunction,
		///< mytest_all ID number
		CreateFunction,
		///< mytest_create ID number

		//
		InputFunction,

		// TecIO
		FileWriterOpenFunction,
		FileWriterCloseFunction,

		ExportToTecplot,
	};

	/// The contructor allows you to specify the id, name, argumenst, and other data associated with \b this \b particular intrinsic.\n
	/// Recall that a separate instance of the library class is created for each intrinsic added.\n
	/// Each separate intrinsic is identified by a unique ID number.\n
	/// In this implementation, the intrinsic specific data is stored as members and assigned on construction.\n
	/// Another valid implementation would be to store nothing locally but the ID and use CASE Statements (or similar) in the implementaion
	///   of getName(), getReadOnly(), etc.
	FishMytest(uint id, const QString& name, int numArguments, const QString& returnDescription,
	           bool readOnly = true, const QString& argumentDescription = QString::null);
	/// Creates 7 instances of this class for each intrinsic, and registers them, then calls delete this.
	virtual QStringList createIntrinsics(IFish* fish);
	/// This example does not create any type, thus returns an empty QStringList.
	virtual QStringList createTypes(IFish*, bool) { return QStringList(); }
	/// Called if the intrinsic appears on the right-hand-side of an assignment.
	virtual void get(IProgram* prog, uint id, const IFishArguments* args, IFishParam* param);
	/// Called if the intrinsic appears on the left-hand-side of an assignment.
	virtual void set(IProgram* prog, uint id, const IFishArguments* args, const IFishParam* param);

	/// Returns the ID number of this particular instance of the library class, must be unique for each intrinsic the library adds.
	virtual uint getID() const { return id_; }
	/// Returns a sub ID for automatically generated version of functions under a general ID.  Optional.
	virtual uint getSubID() const { return 0; }
	/// Returns the name of this intrinsic.
	virtual QString getName() const { return name_; }
	/// Name identifying the plugin that is adding possibly many intrinsics
	virtual QString getPluginName() const;
	/// Returns TRUE if the intrinsic may not appear on the left-hand-side of an assignment.
	virtual bool getReadOnly() const { return readOnly_; }
	/// Returns the number of arguments the intrinsic requires, or -1 if that number may vary.
	virtual int getNumArguments() const { return numArguments_; }
	/// Returns a string describing the return type, used for help only.
	virtual QString getReturnDesc() const { return returnDescription_; }
	/// Returns a string describing the argument types, used for help only.
	virtual QString getArgumentDesc() const { return argumentDescription_; }

	/// Indicates that the library defines data that it wants to save as part of the model state.\n
	/// In this particular case, we only want to save one copy of the data, so we only save if the ID is 0.
	virtual bool willSave() const { return getID() ? false : true; }
	/// Saves/Restores data to the archive.
	virtual void archiveLibrary(IArchive& a);
	virtual void saveLibrary(Archive2& a) const override;
	virtual bool restoreLibrary(Archive2& a, quint64 label) override;
	virtual void remapLibrary(Archive2& a) override;
	/// Clears data to the default settings, when a NEW Model is created.
	virtual void reset();
	/// Destroys this particular instace of the library, representing this intrinsic.
	virtual void destroy() { delete this; }

private:
	uint id_; ///< The ID of this intrinsic.
	QString name_; ///< The name of this intrinsic.
	int numArguments_; ///< The number of arguments required for this intrinsic.
	QString returnDescription_; ///< A description of the return type of this intrinsic.
	bool readOnly_; ///< TRUE if the intrinsic may not be assigned to.
	QString argumentDescription_; ///< A description of the argument types required by this intrinsic.

	static uint version_;
	///< A version number, used to enable backwards compatible save/restore in case of future changes.
	static Double frequency_; ///< The frequency of the sinusoid to generate.
	static Double amplitude_; ///< The amplitude of the sinusoid to generate.
	static Double phase_; ///< The phase of the sinusoid to generate.
	static Double interval_; ///< The interval between points of the sinusoid to generate.
	static qptrdiff number_; ///< The number of points at that interval to generate.
};

/// @}
// EoF
